/**
 * 	Copyright 2011 rkehoe
 *
 * 	Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 * 	You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *	limitations under the License.
 *
 */
package queryable.store;

import static example.domain.objects.DomainObjectBuilder.aNew;

import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import javax.sql.DataSource;

import queryable.store.util.Stopwatch;
import example.domain.objects.Colour;
import example.domain.objects.Vehicle;

/**
 * Simple example using a memory-based JDBC {@link DataSource}.
 * 
 * This example creates 20 thousand random domain {@link Vehicle} objects.
 * It then persists them to memory and then retrieves them using predicates
 * based on properties in those domain objects.
 * 
 * You don't have to do any donkey work - you simply annotate the fields/properties 
 * in you domain object that you may wish to query on at runtime.
 * 
 * If you don't have access to the domain object src then simply write a wrapper
 * and annotate the wrappers fields.
 * 
 * @see #getDataSource()
 *  
 * -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC
 * 
 *  -server -Xmx4000m -XX:+UseParallelGC -XX:+UseParallelOldGC

 * @author rkehoe
 *
 */
public class HelloWorld
{
	/**
     * 
     */
    private static final int SAMPLE_SIZE = 10000;

	public static void main(String[] args) throws Exception
	{
		/*
		 * Create a gaggle of Vehicles
		 */
		ArrayList<Vehicle> list = new ArrayList<Vehicle>();
		for (int i = 0; i < SAMPLE_SIZE; i++)
		{
			Vehicle vehicle = aNew().vehicle().notWith(Colour.Black).build();
            list.add(vehicle);
			if(i%100==0)
            {
	            Vehicle vehicle2 = aNew().vehicle().with(Colour.Black).build();
	            list.add(vehicle2);
            }
		}

		/*
		 * Create your dao on the data store.
		 * That's it as far as set-up is concerned.
		 * You can now do typesafe CRuD operations
		 * through the DAO.
		 */
		IStore<Vehicle> store = Stores.hybridMemoryStore("stressTest",Vehicle.class);		
		store.clear();

		/*
		 * Put stuff IN!
		 */
		Stopwatch sw = Stopwatch.instance("Inserts").start();		
		store.addAll(list);
		sw.stop().printElapsedTime();

		System.out.println("Size of insert list == "+list.size());
		System.out.println("Size of data store after insertion == "+store.size());

		/*
		 * Get stuff OUT. Done!
		 */
		sw = Stopwatch.instance("Extraction").start();
		Collection<Vehicle> collection = store.select("manufacturer = ? and colour = ?", new Object[] {"Fiat","White"});
		sw.stop().printElapsedTime();

		for (Vehicle vehicle : collection)
        {
			//System.out.println(vehicle);	        
        }

		printSystemStats();
//		System.in.read();
		
//		List<Vehicle> list2 = store.select("doors < Max(doors)", null);
//		System.out.println("Size of list2 = "+list2.size());
//		System.out.println(list2.get(0));
		
		int removeWhere = store.remove("manufacturer = ? and colour = ?", new Object[] {"Fiat","White"});
		System.out.println("Have removed "+removeWhere+" rows");
		System.out.println("Size of data store == "+store.size());

		Iterator<Vehicle> iterator = store.iterator();
		while (iterator.hasNext())
        {
	        Vehicle vehicle = (Vehicle) iterator.next();
	        //System.out.println(vehicle);	        	        
        }

		System.out.println("Size of data store == "+store.size());
		
	}

	/**
     * 
     */
    private static void printSystemStats()
    {
    	
    	MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
		MemoryUsage nonHeapMemoryUsage = memoryMXBean.getNonHeapMemoryUsage();
		System.out.println(nonHeapMemoryUsage);
		MemoryUsage heapMemoryUsage = memoryMXBean.getHeapMemoryUsage();
		System.out.println(heapMemoryUsage);
		ManagementFactory.getMemoryMXBean();
		long freeMemory = Runtime.getRuntime().freeMemory();
		System.out.println("FreeMemory="+freeMemory);
		long maxMemory = Runtime.getRuntime().maxMemory();
		System.out.println("MaxMemory="+maxMemory);

		//		memoryMXBean.getHeapMemoryUsage();
//    	com.sun.management.OperatingSystemMXBean.getSystemLoadAverage();
//		ThreadMXBean.getCurrentThreadCpuTime()
//		ThreadMXBean.getCurrentThreadUserTime()
	    
    }
}




